package com.iotechn.unimall.admin.api.warehouseLossGoods;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.iotechn.unimall.core.exception.AdminServiceException;
import com.iotechn.unimall.core.exception.ExceptionDefinition;
import com.iotechn.unimall.core.exception.ServiceException;
import com.iotechn.unimall.data.domain.CategoryDO;
import com.iotechn.unimall.data.domain.WarehouseLossGoodsDO;
import com.iotechn.unimall.data.dto.excel.SkuTotalPriceDTO;
import com.iotechn.unimall.data.dto.warehouse.WarehouseLossGoodsDTO;
import com.iotechn.unimall.data.mapper.CategoryMapper;
import com.iotechn.unimall.data.mapper.PurchaseWarehouseOrderGoodsMapper;
import com.iotechn.unimall.data.mapper.WarehouseLossGoodsMapper;
import com.iotechn.unimall.data.model.Page;
import org.apache.ibatis.session.RowBounds;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.text.DecimalFormat;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;


@Service
public class WarehouseLossGoodsServiceImpl implements WarehouseLossGoodsService {
    @Autowired
    private WarehouseLossGoodsMapper warehouseLossGoodsMapper;
    @Autowired
    private PurchaseWarehouseOrderGoodsMapper purchaseWarehouseOrderGoodsMapper;
    @Autowired
    private CategoryMapper categoryMapper;

    @Override
    public Page<WarehouseLossGoodsDO> list(Integer page, Integer limit, Long adminId) throws ServiceException {
        Wrapper<WarehouseLossGoodsDO> wrapper = new EntityWrapper<WarehouseLossGoodsDO>();
        wrapper.orderBy("id", false);
        Integer count = warehouseLossGoodsMapper.selectCount(wrapper);
        List<WarehouseLossGoodsDO> WarehouseLossGoodsDOS = warehouseLossGoodsMapper.selectPage(new RowBounds((page - 1) * limit, limit), wrapper);
        return new Page<>(WarehouseLossGoodsDOS, page, limit, count);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public WarehouseLossGoodsDO create(WarehouseLossGoodsDO warehouseLossGoodsDO, Long adminId) throws ServiceException {
        Date now = new Date();
        if (warehouseLossGoodsMapper.insert(warehouseLossGoodsDO) > 0) {
            warehouseLossGoodsDO.setId(warehouseLossGoodsDO.getId());
            return warehouseLossGoodsDO;
        }
        throw new AdminServiceException(ExceptionDefinition.ADMIN_UNKNOWN_EXCEPTION);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String update(WarehouseLossGoodsDO warehouseLossGoodsDO, Long adminId) throws ServiceException {
        Long id = warehouseLossGoodsDO.getId();
        if (id == null) {
            return "fail";
        }
        Date now = new Date();
        if (warehouseLossGoodsMapper.updateById(warehouseLossGoodsDO) > 0) {
            return "ok";
        }
        throw new AdminServiceException(ExceptionDefinition.ADMIN_UNKNOWN_EXCEPTION);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String delete(Long id, Long adminId) throws ServiceException {
        if (warehouseLossGoodsMapper.deleteById(id) > 0) {
            return "ok";
        }
        throw new AdminServiceException(ExceptionDefinition.ADMIN_UNKNOWN_EXCEPTION);

    }

    @Override
    public WarehouseLossGoodsDO detail(Long id, Long adminId) throws ServiceException {
        return warehouseLossGoodsMapper.selectById(id);
    }

    @Override
    public Page querySkusByWarehouseId(Integer page, Integer limit, Long warehouseId, String skuIds, String search) {
        LinkedList<Long> childrenIds = new LinkedList<>();
        if (skuIds != null && !"".equals(skuIds)) {
            List<CategoryDO> childrenList = categoryMapper.selectList(new EntityWrapper<CategoryDO>().eq("parent_id", skuIds).eq("store_id",0l));
            // 传入类目拥有的三级类目集合
            // 传入类目没有子类目
            if (CollectionUtils.isEmpty(childrenList)) {
                // 则传入类目为三级类目
                childrenIds.add(Long.valueOf(skuIds));
            } else {

                CategoryDO categoryDO = categoryMapper.selectById(skuIds);

                // 检验传入类目是一级还是二级类目
                if (categoryDO.getParentId() != 0L) {
                    //二级分类
                    childrenList.forEach(item -> {
                        childrenIds.add(item.getId());
                    });
                } else {
                    //一级分类
                    childrenList.forEach(item -> {
                        List<CategoryDO> leafList = categoryMapper.selectList(new EntityWrapper<CategoryDO>().eq("parent_id", item.getId()).eq("store_id",0l));
                        if (!CollectionUtils.isEmpty(leafList)) {
                            leafList.forEach(leafItem -> {
                                childrenIds.add(leafItem.getId());
                            });
                        }
                    });
                }
            }

        }
        Integer start = (page - 1) * limit;
        Integer end = limit;
        List<WarehouseLossGoodsDTO> warehouseLossGoodsDTOS = warehouseLossGoodsMapper.querySkusByWarehouseId(warehouseId, childrenIds, start, end, search);
        if (!CollectionUtils.isEmpty(warehouseLossGoodsDTOS)) {
            warehouseLossGoodsDTOS.stream().map(i -> {
                if (i.getAverPrice() != null) {
                    Float orignalAvgPrice = i.getAverPrice() / 100;
                    i.setAverPrice(orignalAvgPrice);
                }
                return i;
            }).collect(Collectors.toList());
        }
        Integer count = warehouseLossGoodsMapper.countSkusByWarehouseId(warehouseId, childrenIds, search);
        return new Page<>(warehouseLossGoodsDTOS, page, limit, count);
    }

    @Override
    public List<Map<String, Object>> listWarehouseSkusByPara(Long lossCheckId, Long warehouseId) throws ServiceException {
        List<Map<String, Object>> list = warehouseLossGoodsMapper.selectMaps(new EntityWrapper<WarehouseLossGoodsDO>()
                .eq(lossCheckId != null, "loss_check_id", lossCheckId)
                .eq(warehouseId != null, "warehouse_id", warehouseId)
                .setSqlSelect("loss_check_pre_goods_num as lossCheckPreGoodsNum",
                        "loss_check_aft_goods_num as lossCheckAftGoodsNum", "goods_name as goodsName",
                        "goods_bar_code as barCode",
                        "goods_img as img", "spu_id as spuId",
                        "goods_unit as unit",
                        "sku_name as skuName",
                        "spu_name as spuName",
                        "sku_id as skuId",
                        "(select ifnull(sum(uwg.warehouse_sku_stock),0) from unimall_warehouse_goods uwg where uwg.sku_id = unimall_warehouse_loss_goods.sku_id and uwg.warehouse_id = " + warehouseId + ") as warehouseSkuNum",
                        "loss_check_goods_num as lossCheckGoodsNum", "loss_check_goods_amount as lossCheckGoodsAmount"));

        List<Long> skuIds = list.stream().map(item -> {
            return Long.valueOf(String.valueOf(item.get("skuId")));
        }).collect(Collectors.toList());
        //List<SkuTotalPriceDTO> skuTotalPriceDTOS = purchaseWarehouseOrderGoodsMapper.summaryGoods(null, null, skuIds, null);
        /*Map<Long, SkuTotalPriceDTO> map = skuTotalPriceDTOS.stream().collect(Collectors.toMap(SkuTotalPriceDTO::getSkuId, Function.identity()));

        list.stream().map(i -> {
            Long skuId = Long.valueOf(String.valueOf(i.get("skuId")));
            if (!map.isEmpty() && map.containsKey(skuId)) {
                SkuTotalPriceDTO skuTotalPriceDTO = map.get(skuId);
                DecimalFormat decimalFormat = new DecimalFormat(".00");
                String total = decimalFormat.format(skuTotalPriceDTO.getPrice());
                i.put("averPrice", Float.valueOf(total));
            }
            return i;
        }).collect(Collectors.toList());*/
        return list;
    }

}